Fix for #104811, Padraig O'Briain:
authorMatthias Clasen <maclas@gmx.de>
Thu, 12 Feb 2004 23:58:46 +0000 (23:58 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Thu, 12 Feb 2004 23:58:46 +0000 (23:58 +0000)
Fri Feb 13 00:54:59 2004  Matthias Clasen  <maclas@gmx.de>

Fix for #104811, Padraig O'Briain:

* gtk/gtkscale.h:
* gtk/gtkscale.c (_gtk_scale_clear_layout):
* gtk/gtkscale.c (gtk_scale_get_layout_offsets):
* gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
text and its position from a GtkScale, to make it more accessible.
* gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
* gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the
new GtkScale vfunc.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/reference/ChangeLog
docs/reference/gtk/gtk-sections.txt
gtk/gtkhscale.c
gtk/gtkscale.c
gtk/gtkscale.h
gtk/gtkvscale.c

index a2f84e98a0edf5e889e9edc0fb1f084aec9a2d30..257202a37c0e7d4e61c935e8c4a5a41a460d23d0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Fri Feb 13 00:54:59 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Fix for #104811, Padraig O'Briain:
+
+       * gtk/gtkscale.h:
+       * gtk/gtkscale.c (_gtk_scale_clear_layout): 
+       * gtk/gtkscale.c (gtk_scale_get_layout_offsets): 
+       * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+       text and its position from a GtkScale, to make it more accessible. 
+       * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+       * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the 
+       new GtkScale vfunc.
+
 Thu Feb 12 17:59:52 2004  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkicontheme.c (gtk_icon_theme_get_search_path): 
index a2f84e98a0edf5e889e9edc0fb1f084aec9a2d30..257202a37c0e7d4e61c935e8c4a5a41a460d23d0 100644 (file)
@@ -1,3 +1,16 @@
+Fri Feb 13 00:54:59 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Fix for #104811, Padraig O'Briain:
+
+       * gtk/gtkscale.h:
+       * gtk/gtkscale.c (_gtk_scale_clear_layout): 
+       * gtk/gtkscale.c (gtk_scale_get_layout_offsets): 
+       * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+       text and its position from a GtkScale, to make it more accessible. 
+       * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+       * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the 
+       new GtkScale vfunc.
+
 Thu Feb 12 17:59:52 2004  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkicontheme.c (gtk_icon_theme_get_search_path): 
index a2f84e98a0edf5e889e9edc0fb1f084aec9a2d30..257202a37c0e7d4e61c935e8c4a5a41a460d23d0 100644 (file)
@@ -1,3 +1,16 @@
+Fri Feb 13 00:54:59 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Fix for #104811, Padraig O'Briain:
+
+       * gtk/gtkscale.h:
+       * gtk/gtkscale.c (_gtk_scale_clear_layout): 
+       * gtk/gtkscale.c (gtk_scale_get_layout_offsets): 
+       * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+       text and its position from a GtkScale, to make it more accessible. 
+       * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+       * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the 
+       new GtkScale vfunc.
+
 Thu Feb 12 17:59:52 2004  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkicontheme.c (gtk_icon_theme_get_search_path): 
index a2f84e98a0edf5e889e9edc0fb1f084aec9a2d30..257202a37c0e7d4e61c935e8c4a5a41a460d23d0 100644 (file)
@@ -1,3 +1,16 @@
+Fri Feb 13 00:54:59 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Fix for #104811, Padraig O'Briain:
+
+       * gtk/gtkscale.h:
+       * gtk/gtkscale.c (_gtk_scale_clear_layout): 
+       * gtk/gtkscale.c (gtk_scale_get_layout_offsets): 
+       * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+       text and its position from a GtkScale, to make it more accessible. 
+       * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+       * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the 
+       new GtkScale vfunc.
+
 Thu Feb 12 17:59:52 2004  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkicontheme.c (gtk_icon_theme_get_search_path): 
index a2f84e98a0edf5e889e9edc0fb1f084aec9a2d30..257202a37c0e7d4e61c935e8c4a5a41a460d23d0 100644 (file)
@@ -1,3 +1,16 @@
+Fri Feb 13 00:54:59 2004  Matthias Clasen  <maclas@gmx.de>
+
+       Fix for #104811, Padraig O'Briain:
+
+       * gtk/gtkscale.h:
+       * gtk/gtkscale.c (_gtk_scale_clear_layout): 
+       * gtk/gtkscale.c (gtk_scale_get_layout_offsets): 
+       * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+       text and its position from a GtkScale, to make it more accessible. 
+       * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+       * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the 
+       new GtkScale vfunc.
+
 Thu Feb 12 17:59:52 2004  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkicontheme.c (gtk_icon_theme_get_search_path): 
index 84f3fedfb911d96ef5f0e168d5a1addfb0a417f8..e9a17453a8637c788f8562ec084899085887f6bd 100644 (file)
@@ -1,3 +1,8 @@
+Fri Feb 13 00:54:24 2004  Matthias Clasen  <maclas@gmx.de>
+
+       * gtk/gtk-sections.txt: Add gtk_scale_get_layout
+       and gtk_scale_get_layout_offsets.
+
 Thu Feb 12 23:56:12 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtk-sections.txt: Add gtk_tooltips_get_info_from_tip_window.
index d6908af03aad8840f1e2f91a208f2645a4cb5101..c191e1a95b88617b83136ac9b7fa1e1f44fe6e7b 100644 (file)
@@ -2476,6 +2476,8 @@ gtk_scale_set_value_pos
 gtk_scale_get_digits
 gtk_scale_get_draw_value
 gtk_scale_get_value_pos
+gtk_scale_get_layout
+gtk_scale_get_layout_offsets
 <SUBSECTION Standard>
 GTK_SCALE
 GTK_IS_SCALE
index 13c6fd2a551675f066dd01d7b60bb11591ad871b..4ca302e4e6a4f47bfb919399a6656244418e64a4 100644 (file)
@@ -37,6 +37,10 @@ static void     gtk_hscale_init             (GtkHScale      *hscale);
 static gboolean gtk_hscale_expose           (GtkWidget      *widget,
                                              GdkEventExpose *event);
 
+static void     gtk_hscale_get_layout_offsets (GtkScale       *scale,
+                                               gint           *x,
+                                               gint           *y);
+
 GType
 gtk_hscale_get_type (void)
 {
@@ -69,13 +73,17 @@ gtk_hscale_class_init (GtkHScaleClass *class)
 {
   GtkWidgetClass *widget_class;
   GtkRangeClass *range_class;
+  GtkScaleClass *scale_class;
   
   widget_class = GTK_WIDGET_CLASS (class);
   range_class = GTK_RANGE_CLASS (class);
+  scale_class = GTK_SCALE_CLASS (class);
 
   parent_class = g_type_class_peek_parent (class);
 
   range_class->slider_detail = "hscale";
+
+  scale_class->get_layout_offsets = gtk_hscale_get_layout_offsets;
   
   widget_class->expose_event = gtk_hscale_expose;
 }
@@ -145,13 +153,9 @@ static gboolean
 gtk_hscale_expose (GtkWidget      *widget,
                    GdkEventExpose *event)
 {
-  GtkRange *range;
-  GtkHScale *hscale;
   GtkScale *scale;
   
-  range = GTK_RANGE (widget);
   scale = GTK_SCALE (widget);
-  hscale = GTK_HSCALE (widget);
 
   /* We need to chain up _first_ so the various geometry members of
    * GtkRange struct are updated.
@@ -162,58 +166,12 @@ gtk_hscale_expose (GtkWidget      *widget,
   if (scale->draw_value)
     {
       PangoLayout *layout;
-      PangoRectangle logical_rect;
-      gchar *txt;
       gint x, y;
       GtkStateType state_type;
-      gint value_spacing;
 
-      gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
-      
-      txt = _gtk_scale_format_value (scale,
-                                     GTK_RANGE (scale)->adjustment->value);
-      
-      layout = gtk_widget_create_pango_layout (widget, txt);
-      g_free (txt);
-      
-      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-      
-      switch (scale->value_pos)
-        {
-        case GTK_POS_LEFT:
-          x = range->range_rect.x - value_spacing - logical_rect.width;
-          y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
-          break;
-          
-        case GTK_POS_RIGHT:
-          x = range->range_rect.x + range->range_rect.width + value_spacing;
-          y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
-          break;
-          
-        case GTK_POS_TOP:
-          x = range->slider_start +
-            (range->slider_end - range->slider_start - logical_rect.width) / 2;
-          x = CLAMP (x, 0, widget->allocation.width - logical_rect.width);
-          y = range->range_rect.y - logical_rect.height - value_spacing;
-          break;
-          
-        case GTK_POS_BOTTOM:
-          x = range->slider_start +
-            (range->slider_end - range->slider_start - logical_rect.width) / 2;
-          x = CLAMP (x, 0, widget->allocation.width - logical_rect.width);
-          y = range->range_rect.y + range->range_rect.height + value_spacing;
-          break;
-
-        default:
-          g_return_val_if_reached (FALSE);
-          x = 0;
-          y = 0;
-          break;
-        }
-
-      x += widget->allocation.x;
-      y += widget->allocation.y;
-      
+      layout = gtk_scale_get_layout (scale);
+      gtk_scale_get_layout_offsets (scale, &x, &y);
+
       state_type = GTK_STATE_NORMAL;
       if (!GTK_WIDGET_IS_SENSITIVE (scale))
         state_type = GTK_STATE_INSENSITIVE;
@@ -228,8 +186,74 @@ gtk_hscale_expose (GtkWidget      *widget,
                         x, y,
                         layout);
 
-      g_object_unref (layout);
     }
   
   return FALSE;
 }
+
+static void     
+gtk_hscale_get_layout_offsets (GtkScale *scale,
+                               gint     *x,
+                               gint     *y)
+{
+  GtkWidget *widget;
+  GtkRange *range;
+  GtkScale *scale;
+  PangoLayout *layout;
+  PangoRectangle logical_rect;
+  gint value_spacing;
+
+  widget = GTK_WIDGET (scale);
+  layout = gtk_scale_get_layout (scale);
+      
+  if (!layout)    
+    {
+      *x = 0;
+      *y = 0;
+
+      return;
+    }
+
+  gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
+
+  range = GTK_RANGE (widget);
+  scale = GTK_SCALE (widget);
+
+  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+      
+  switch (scale->value_pos)
+    {
+     case GTK_POS_LEFT:
+       *x = range->range_rect.x - value_spacing - logical_rect.width;
+       *y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
+       break;
+          
+    case GTK_POS_RIGHT:
+      *x = range->range_rect.x + range->range_rect.width + value_spacing;
+      *y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
+      break;
+          
+    case GTK_POS_TOP:
+      *x = range->slider_start +
+        (range->slider_end - range->slider_start - logical_rect.width) / 2;
+      *x = CLAMP (*x, 0, widget->allocation.width - logical_rect.width);
+      *y = range->range_rect.y - logical_rect.height - value_spacing;
+      break;
+          
+    case GTK_POS_BOTTOM:
+      *x = range->slider_start +
+        (range->slider_end - range->slider_start - logical_rect.width) / 2;
+      *x = CLAMP (*x, 0, widget->allocation.width - logical_rect.width);
+      *y = range->range_rect.y + range->range_rect.height + value_spacing;
+      break;
+
+    default:
+      g_return_val_if_reached (FALSE);
+      *x = 0;
+      *y = 0;
+      break;
+    }
+
+  *x += widget->allocation.x;
+  *y += widget->allocation.y;
+}
index 6f65ca7de6648654d04eed27197fd374bfec511e..003d56461dc0b79b1cba21cf07610a3df4c1286e 100644 (file)
                                 *    unrelated code portions otherwise
                                 */
 
+#define GTK_SCALE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCALE, GtkScalePrivate))
+
+typedef struct _GtkScalePrivate GtkScalePrivate;
+
+struct _GtkScalePrivate
+{
+  PangoLayout *layout;
+};
+
 enum {
   PROP_0,
   PROP_DIGITS,
@@ -68,6 +77,9 @@ static void gtk_scale_style_set        (GtkWidget     *widget,
                                         GtkStyle      *previous);
 static void gtk_scale_get_range_border (GtkRange      *range,
                                         GtkBorder     *border);
+static void gtk_scale_finalize         (GObject       *object);
+static void gtk_scale_screen_changed   (GtkWidget     *widget,
+                                        GdkScreen     *old_screen);
 
 GType
 gtk_scale_get_type (void)
@@ -135,8 +147,10 @@ gtk_scale_class_init (GtkScaleClass *class)
   
   gobject_class->set_property = gtk_scale_set_property;
   gobject_class->get_property = gtk_scale_get_property;
+  gobject_class->finalize = gtk_scale_finalize;
 
   widget_class->style_set = gtk_scale_style_set;
+  widget_class->screen_changed = gtk_scale_screen_changed;
 
   range_class->get_range_border = gtk_scale_get_range_border;
   
@@ -312,6 +326,8 @@ gtk_scale_class_init (GtkScaleClass *class)
 
   add_slider_binding (binding_set, GDK_KP_End, 0,
                       GTK_SCROLL_END);
+
+  g_type_class_add_private (gobject_class, sizeof (GtkScalePrivate));
 }
 
 static void
@@ -407,6 +423,7 @@ gtk_scale_set_digits (GtkScale *scale,
       if (scale->draw_value)
        range->round_digits = digits;
       
+      _gtk_scale_clear_layout (scale);
       gtk_widget_queue_resize (GTK_WIDGET (scale));
 
       g_object_notify (G_OBJECT (scale), "digits");
@@ -437,6 +454,8 @@ gtk_scale_set_draw_value (GtkScale *scale,
       else
        GTK_RANGE (scale)->round_digits = -1;
 
+      _gtk_scale_clear_layout (scale);
+
       gtk_widget_queue_resize (GTK_WIDGET (scale));
 
       g_object_notify (G_OBJECT (scale), "draw_value");
@@ -461,6 +480,7 @@ gtk_scale_set_value_pos (GtkScale        *scale,
     {
       scale->value_pos = pos;
 
+      _gtk_scale_clear_layout (scale);
       if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
        gtk_widget_queue_resize (GTK_WIDGET (scale));
 
@@ -586,9 +606,17 @@ gtk_scale_style_set (GtkWidget *widget,
   
   range->min_slider_size = slider_length;
   
+  _gtk_scale_clear_layout (GTK_SCALE (widget));
+
   (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
 }
 
+static void
+gtk_scale_screen_changed (GtkWidget *widget,
+                          GdkScreen *old_screen)
+{
+  _gtk_scale_clear_layout (GTK_SCALE (widget));
+}
 
 /**
  * _gtk_scale_format_value:
@@ -618,3 +646,103 @@ _gtk_scale_format_value (GtkScale *scale,
     return g_strdup_printf ("%0.*f", scale->digits,
                             value);
 }
+
+static void
+gtk_scale_finalize (GObject *object)
+{
+  GtkScale *scale;
+
+  g_return_if_fail (GTK_IS_SCALE (object));
+
+  scale = GTK_SCALE (object);
+
+  _gtk_scale_clear_layout (scale);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * gtk_scale_get_layout:
+ * @scale: A #GtkScale
+ *
+ * Gets the #PangoLayout used to display the scale. The returned object
+ * is owned by the scale so does not need to be freed by the caller. 
+ *
+ * Return value: the #PangoLayout for this scale, or %NULL if the draw_value property
+ *    is %FALSE.
+ *   
+ * Since: 2.4
+ **/
+PangoLayout *
+gtk_scale_get_layout (GtkScale *scale)
+{
+  GtkScalePrivate *priv = GTK_SCALE_GET_PRIVATE (scale);
+  gchar *txt;
+
+  g_return_val_if_fail (GTK_IS_SCALE (scale), NULL);
+
+  if (!priv->layout)
+    {
+      if (scale->draw_value)
+       priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (scale), NULL);
+    }
+
+  if (scale->draw_value) 
+    {
+      txt = _gtk_scale_format_value (scale,
+                                    GTK_RANGE (scale)->adjustment->value);
+      pango_layout_set_text (priv->layout, txt, -1);
+      g_free (txt);
+    }
+
+  return priv->layout;
+}
+
+/**
+ * gtk_scale_get_layout_offsets:
+ * @scale: a #GtkScale
+ * @x: location to store X offset of layout, or %NULL
+ * @y: location to store Y offset of layout, or %NULL
+ *
+ * Obtains the coordinates where the scale will draw the #PangoLayout
+ * representing the text in the scale. Remember
+ * when using the #PangoLayout function you need to convert to
+ * and from pixels using PANGO_PIXELS() or #PANGO_SCALE. 
+ *
+ * If the draw_value property is %FALSE, the return values are 
+ * undefined.
+ *
+ * Since: 2.4
+ **/
+void 
+gtk_scale_get_layout_offsets (GtkScale *scale,
+                              gint     *x,
+                              gint     *y)
+{
+  gint local_x, local_y;
+
+  g_return_val_if_fail (GTK_IS_SCALE (scale), NULL);
+
+  if (GTK_SCALE_GET_CLASS (scale)->get_layout_offsets)
+    (GTK_SCALE_GET_CLASS (scale)->get_layout_offsets) (scale, &local_x, &local_y);
+
+  if (x)
+    *x = local_x;
+  
+  if (y)
+    *y = local_y;
+}
+
+void _gtk_scale_clear_layout (GtkScale *scale)
+{
+  GtkScalePrivate *priv = GTK_SCALE_GET_PRIVATE (scale);
+
+  g_return_if_fail (GTK_IS_SCALE (scale));
+
+  if (priv->layout)
+    {
+      g_object_unref (priv->layout);
+      priv->layout = NULL;
+    }
+}
+
index 82f3fea0cb6a8849af0d4b738e8ac34df2dfa504..3623142519e432917182fe40a58bc66dc164c687 100644 (file)
@@ -66,8 +66,10 @@ struct _GtkScaleClass
   
   void (* draw_value) (GtkScale *scale);
 
+  void (* get_layout_offsets) (GtkScale *scale,
+                               gint     *x,
+                               gint     *y);
   /* Padding for future expansion */
-  void (*_gtk_reserved1) (void);
   void (*_gtk_reserved2) (void);
   void (*_gtk_reserved3) (void);
   void (*_gtk_reserved4) (void);
@@ -85,12 +87,18 @@ void            gtk_scale_set_value_pos  (GtkScale        *scale,
                                           GtkPositionType  pos);
 GtkPositionType gtk_scale_get_value_pos  (GtkScale        *scale);
 
+PangoLayout     *gtk_scale_get_layout        (GtkScale        *scale);
+void            gtk_scale_get_layout_offsets (GtkScale        *scale,
+                                             gint            *x,
+                                             gint            *y);
+void    _gtk_scale_clear_layout    (GtkScale        *scale);
 
 void    _gtk_scale_get_value_size  (GtkScale        *scale,
                                     gint            *width,
                                     gint            *height);
-gchar  *_gtk_scale_format_value   (GtkScale        *scale,
-                                   gdouble          value);
+gchar  *_gtk_scale_format_value    (GtkScale        *scale,
+                                    gdouble          value);
+
 
 #ifdef __cplusplus
 }
index ae28fddfdcb052f2b21db7e6e511cccd39f05a15..86a4d93d410a7fdbd5416f5b1c62443ad8bf4c61 100644 (file)
@@ -39,6 +39,10 @@ static void     gtk_vscale_init             (GtkVScale      *vscale);
 static gboolean gtk_vscale_expose           (GtkWidget      *widget,
                                              GdkEventExpose *event);
 
+static void    gtk_vscale_get_layout_offsets (GtkScale         *scale,
+                                               gint            *x,
+                                               gint            *y);
+
 GType
 gtk_vscale_get_type (void)
 {
@@ -71,14 +75,18 @@ gtk_vscale_class_init (GtkVScaleClass *class)
 {
   GtkWidgetClass *widget_class;
   GtkRangeClass *range_class;
+  GtkScaleClass *scale_class;
   
   widget_class = GTK_WIDGET_CLASS (class);
   range_class = GTK_RANGE_CLASS (class); 
+  scale_class = GTK_SCALE_CLASS (class); 
 
   parent_class = g_type_class_peek_parent (class);
 
   range_class->slider_detail = "vscale";
   
+  scale_class->get_layout_offsets = gtk_vscale_get_layout_offsets;
+
   widget_class->expose_event = gtk_vscale_expose;
 }
 
@@ -147,13 +155,9 @@ static gboolean
 gtk_vscale_expose (GtkWidget      *widget,
                    GdkEventExpose *event)
 {
-  GtkRange *range;
-  GtkVScale *vscale;
   GtkScale *scale;
   
-  range = GTK_RANGE (widget);
   scale = GTK_SCALE (widget);
-  vscale = GTK_VSCALE (widget);
   
   /* We need to chain up _first_ so the various geometry members of
    * GtkRange struct are updated.
@@ -164,56 +168,12 @@ gtk_vscale_expose (GtkWidget      *widget,
   if (scale->draw_value)
     {
       PangoLayout *layout;
-      PangoRectangle logical_rect;
-      gchar *txt;
       gint x, y;
       GtkStateType state_type;
-      gint value_spacing;
 
-      gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
-      
-      txt = _gtk_scale_format_value (scale,
-                                     GTK_RANGE (scale)->adjustment->value);
-      
-      layout = gtk_widget_create_pango_layout (widget, txt);
-      g_free (txt);
-      
-      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-      
-      switch (scale->value_pos)
-        {
-        case GTK_POS_LEFT:
-          x = range->range_rect.x - logical_rect.width - value_spacing;
-          y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
-          y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
-          break;
-          
-        case GTK_POS_RIGHT:
-          x = range->range_rect.x + range->range_rect.width + value_spacing;
-          y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
-          y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
-          break;
-          
-        case GTK_POS_TOP:
-          x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
-          y = range->range_rect.y - logical_rect.height - value_spacing;
-          break;
-          
-        case GTK_POS_BOTTOM:
-          x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
-          y = range->range_rect.y + range->range_rect.height + value_spacing;
-          break;
-
-        default:
-          g_return_val_if_reached (FALSE);
-          x = 0;
-          y = 0;
-          break;
-        }
-      
-      x += widget->allocation.x;
-      y += widget->allocation.y;
-      
+      layout = gtk_scale_get_layout (widget);
+      gtk_scale_get_layout_offsets (widget, &x, &y);
+
       state_type = GTK_STATE_NORMAL;
       if (!GTK_WIDGET_IS_SENSITIVE (scale))
         state_type = GTK_STATE_INSENSITIVE;
@@ -227,9 +187,74 @@ gtk_vscale_expose (GtkWidget      *widget,
                         "vscale",
                         x, y,
                         layout);
-
-      g_object_unref (layout);
     }
   
   return FALSE;
+
+}
+
+static void
+gtk_vscale_get_layout_offsets (GtkScale *scale,
+                               gint     *x,
+                               gint     *y)
+{
+  GtkWidget *widget;
+  GtkRange *range;
+  GtkScale *scale;
+  PangoLayout *layout;
+  PangoRectangle logical_rect;
+  gint value_spacing;
+
+  widget = GTK_WIDGET (scale);
+  layout = gtk_scale_get_layout (scale);
+      
+  if (!layout)
+    {
+      *x = 0;
+      *y = 0;
+
+      return;
+    }
+
+  range = GTK_RANGE (widget);
+  scale = GTK_SCALE (widget);
+
+  gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
+      
+  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+    
+  switch (scale->value_pos)
+    {
+    case GTK_POS_LEFT:
+      *x = range->range_rect.x - logical_rect.width - value_spacing;
+      *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
+      *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
+      break;
+      
+    case GTK_POS_RIGHT:
+      *x = range->range_rect.x + range->range_rect.width + value_spacing;
+      *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
+      *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
+      break;
+          
+    case GTK_POS_TOP:
+      *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
+      *y = range->range_rect.y - logical_rect.height - value_spacing;
+      break;
+          
+    case GTK_POS_BOTTOM:
+      *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
+      *y = range->range_rect.y + range->range_rect.height + value_spacing;
+      break;
+
+    default:
+      g_return_val_if_reached (FALSE);
+      *x = 0;
+      *y = 0;
+      break;
+    }
+
+  *x += widget->allocation.x;
+  *y += widget->allocation.y;
 }
+